#ifndef _CHANNEL_H
#define _CHANNEL_H

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <string>
#include <ProcessQueue.h>
//#include <Queue.h>
#include <malloc_align.h>
#include <ProcessComposition.h>
#include <Alting.h>

#include <csp_shared_types.h>


using namespace std;
class Channel
{
	public:
		Channel(int type, long id);
		~Channel();
		ProcessComposition* Write(ProcessComposition *p, ls_addr_t w_addr, ls_size_t size);
		ProcessComposition* Read(ProcessComposition *p, ls_addr_t w_addr, ls_size_t size);
/*
		channel_link_t* Write(ProcessComposition *p, ls_addr_t w_addr, ls_size_t size);
		channel_link_t* Read(ProcessComposition *p, ls_addr_t w_addr, ls_size_t size);
*/
		long GetID();
		void Lock();
		void Unlock();
		void Poison();
		bool IsPoisoned();

		/* Operations used by ALT */
		bool AltingEnable(Alting *alt, int idx);
		bool AltingDisable();
		ProcessComposition* Accept();
/*
		channel_link_t* Accept();
*/		
	private:
		void CheckChannelOperation(bool read,ProcessComposition* p, ls_size_t size);
		ProcessComposition* DoChannelOperation(bool read, ProcessComposition* p, ls_size_t size, ls_addr_t);
		ProcessQueue r_procs;
		ProcessQueue w_procs;
		void Release(ProcessQueue &procs, int op_ret_);

/*
		channel_link_t* DoChannelOperation(bool read, ProcessComposition* p, ls_size_t size, ls_addr_t);
		Queue <channel_link_t> r_procs;
		Queue <channel_link_t> w_procs;
		void Release(Queue <channel_link_t> &procs, int op_ret_);
*/
		int type; 
		long id; 
		pthread_mutex_t chan_lock;
		int32_t r_pid, w_pid; // one2X or X2one channels
		ls_size_t msg_size_in_channel;

		pthread_mutex_t alt_lock;
		Alting *altHook;
		int altIdx;

		bool poison;
};

#endif
